module Mole
  class Crawler
    include Capybara::DSL

    CSV_HEADERS = %w(品名 品牌 品牌编号 适用车型 单价 市场参考价 库存)

    def initialize(output=nil)
      @output = output || Mole.root.join("tmp/result-#{Time.now.strftime('%Y%m%d%H%M%S')}.csv")
      @tesseract = Tesseract::Engine.new do |e|
        e.language = :eng
        e.blacklist = '~`!@#$%^&*()-_=+[]{}\|/?<>,.0123456789'
        e.path = '/usr/share/tesseract-ocr/tessdata'
      end
    end

    def crawl
      visit_entrance
      total_pages = find('#headpage').text.split(/\W/).last.to_i.tap{|pages| puts "Total Pages: #{pages}"}
      CSV.open(@output, 'w', quote_char: '"', write_headers: true, headers: CSV_HEADERS) do |csv|
        (1 .. total_pages).step(1) do |page_num|
          each_product {|product| csv << product}
          within('.cx_list') do
            click_link (page_num + 1).to_s unless page_num == total_pages  # go to next page
          end
        end
      end
    end

    private
    def read_captcha
      retrieve_captcha_data
      ocr_captcha
    end

    def ocr_captcha
      @tesseract.text_for('tmp/captcha.png').upcase.gsub(/\W/, '')
    end

    def retrieve_captcha_data
      data_url = page.evaluate_script <<-JS
        (function() {
          var img = document.getElementById('ImgVerify');

          var canvas = document.createElement('canvas');
          canvas.width = img.width;
          canvas.height = img.height;

          var ctx = canvas.getContext("2d");
          ctx.drawImage(img, 0, 0);

          return canvas.toDataURL("image/png");
        })();
      JS

      File.open('tmp/captcha.png', 'wb') do |f|
        f.write Base64.decode64(data_url.split(',')[-1])
      end
    end

    def wait_for_redirect_to(target_path)
      Timeout.timeout(Capybara.default_max_wait_time) do
        loop do
          break if current_path === target_path
        end
      end
    end

    def visit_entrance
      visit 'http://topqp.com/Query.aspx'
      login
      find('#Brand').click
      find('#allcity-popup-menu li[title="fghij-city"]').click
      find('#allcity-popup-menu ul#fghij-city li[title="G 盖茨"]').click
      when_ajax_done {click_button 'btnKeyWord'}
    end

    def login
      click_link '[ 登录 ]'
      wait_for_ajax
      wait_for_redirect_to '/Member/Login.aspx'
      # sleep(5)

      captcha = read_captcha

      fill_in 'LoginName', with: 'goldenkiller'
      fill_in 'LoginPassword', with: '888888'
      fill_in 'VerifyCode', with: captcha

      click_button '登录'
      wait_for_ajax
      wait_for_redirect_to('/Query.aspx')
      wait_for_ajax
    end

    def each_product
      when_ajax_done do
        # puts page.evaluate_script %[$('#Productcontainer .list_1').html()]
        all('#Productcontainer .list_1').each do |row|
          # puts row['innerHTML']
          yield (row.find('.tabs_6_b').all('li span').to_a + row.all('.tabs_6_c').first.all('li span').to_a).map(&:text)
        end
      end
    end

    def when_ajax_done
      wait_for_ajax
      yield if block_given?
    end

    def wait_for_ajax
      Timeout.timeout(Capybara.default_max_wait_time) do
        loop do
          break if page.evaluate_script('jQuery.active').zero?
        end
      end
    rescue => e
      $stderr.puts e.message
      raise e
    end

  end
end